﻿using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewEngines;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;

namespace SharpSoft.Web
{
    /// <summary>
    /// 静态化辅助类
    /// </summary>
    public static class StaticizeHelper
    {
        /// <summary>
        /// 根据根目录和路由信息获取静态文件的完整文件名
        /// </summary>
        /// <param name="rootPath"></param>
        /// <param name="route"></param>
        /// <returns></returns>
        private static string GetFileName(string rootPath, string[] route)
        {
            List<string> list = new List<string>();
            list.Add(rootPath);

            if (route == null || route.Length == 0)
            {
                list.Add("defaultpage.html");
            }
            else
            {
                for (int i = 0; i < route.Length; i++)
                {//将各部分转为小写
                    if (route[i] != null)
                    {
                        if (i == route.Length - 1)
                        {
                            list.Add(route[i].ToLower() + ".html");//最后的加上.html后缀
                        }
                        else
                        {
                            list.Add(route[i].ToLower());
                        }


                    }
                }
            }

            var filename = System.IO.Path.Combine(list.ToArray());
            return filename;
        }
        /// <summary>
        /// 将路由信息处理成规范的key
        /// </summary>
        /// <param name="route"></param>
        /// <returns></returns>
        public static string GetRouteKey(string[] route)
        {
            if (route == null || route.Length == 0)
            {
                return "defaultpage";
            }
            return string.Join('_', route).ToLower();
        }
        /// <summary>
        /// 静态化文件是否存在
        /// </summary>
        /// <param name="rootPath"></param>
        /// <param name="route"></param>
        /// <returns></returns>
        public static bool ExistsStaticizeFile(string rootPath, string[] route)
        {
            var filename = GetFileName(rootPath, route);
            return System.IO.File.Exists(filename);
        }
        /// <summary>
        /// 读取静态化缓存文件内容
        /// </summary>
        /// <param name="rootPath"></param>
        /// <param name="route"></param>
        /// <returns></returns>
        public static string ReadStaticizeFile(string rootPath, string[] route)
        {
            var filename = GetFileName(rootPath, route);
            using (var fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
            {
                using (var sr = new StreamReader(fs, Encoding.UTF8))
                {
                    return sr.ReadToEnd();
                }
            }
        }

        ///// <summary>
        ///// 获取静态化文件最后修改时间
        ///// </summary>
        ///// <param name="rootPath"></param>
        ///// <param name="route"></param>
        ///// <returns></returns>
        //public static DateTime? GetStaticizeFileModifierTime(string rootPath, string[] route)
        //{
        //    var filename = GetFileName(rootPath, route);
        //    if (!System.IO.File.Exists(filename))
        //    {
        //        return null;
        //    }
        //    return System.IO.File.GetLastWriteTime(filename);
        //}
        /// <summary>
        /// 写入静态文件
        /// </summary>
        /// <param name="rootPath"></param>
        /// <param name="route"></param>
        /// <param name="content"></param>
        public static void WriteStaticizeFile(string rootPath, string[] route, string content)
        {
            var filename = GetFileName(rootPath, route);
            var folder = System.IO.Path.GetDirectoryName(filename);
            if (!Directory.Exists(folder))
            {
                Directory.CreateDirectory(folder);
            }
            using (var fs = new FileStream(filename, FileMode.Create, FileAccess.Write))
            {
                using (var sw = new StreamWriter(fs, Encoding.UTF8))
                {
                    sw.Write(content);
                }
            }

        }
        /// <summary>
        /// 删除缓存文件
        /// </summary>
        /// <param name="rootPath"></param>
        /// <param name="route"></param>
        public static void DeleteStaticizeFile(string rootPath, string[] route)
        {
            var filename = GetFileName(rootPath, route);
            if (File.Exists(filename))
            {
                File.Delete(filename);
            } 
        }
        /// <summary>
        /// 获取页面视图的渲染结果
        /// </summary>
        /// <param name="controller"></param>
        /// <param name="viewName"></param>
        /// <param name="model"></param>
        /// <param name="partial"></param>
        /// <returns></returns>
        public static async Task<string> GetViewRenderResult(this Controller controller, string viewName, object model, bool partial = false)
        {
            if (string.IsNullOrEmpty(viewName))
            {
                viewName = controller.ControllerContext.ActionDescriptor.ActionName;
            }
            controller.ViewData.Model = model;
            using (var writer = new StringWriter())
            {
                IViewEngine viewEngine = controller.HttpContext.RequestServices.GetService(typeof(ICompositeViewEngine)) as ICompositeViewEngine;
                ViewEngineResult viewResult = viewEngine.FindView(controller.ControllerContext, viewName, !partial);
                if (viewResult.Success == false)
                {
                    return $"A view with the name {viewName} could not be found";
                }
                ViewContext viewContext = new ViewContext(
                    controller.ControllerContext,
                    viewResult.View,
                    controller.ViewData,
                    controller.TempData,
                    writer,
                    new HtmlHelperOptions()
                );
                await viewResult.View.RenderAsync(viewContext);
                return writer.GetStringBuilder().ToString();
            }
        }
    }
}
